<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Figures</title>
<meta http-equiv="Content-Type" Content="text/html; charset=utf-8">
<meta content="Under the Hood: Reduce EXE and DLL Size with LIBCTINY.LIB." name="Description">
<link rel="stylesheet" type="text/css" href="../../../styles/styles.css">
</head>

<body>

<hr color="#000080">
<a name="fig1">Figure 1</a> Hello World .MAP File<br>
<pre class=code>
Address         Publics by Value             Rva+Base     Lib:Object
0001:00000000   _main                        00401000 f   hello.obj
0001:0000000c   _printf                      0040100c f   LIBC:printf.obj
0001:0000003d   _mainCRTStartup              0040103d f   LIBC:crt0.obj
0001:0000011c   __amsg_exit                  0040111c f   LIBC:crt0.obj
0001:00000165   __stbuf                      00401165 f   LIBC:_sftbuf.obj
0001:000001f2   __ftbuf                      004011f2 f   LIBC:_sftbuf.obj
0001:0000022f   __output                     0040122f f   LIBC:output.obj
0001:00000a39   ___initstdio                 00401a39 f   LIBC:_file.obj
0001:00000ade   ___endstdio                  00401ade f   LIBC:_file.obj
0001:00000af2   __cinit                      00401af2 f   LIBC:crt0dat.obj
0001:00000b1f   _exit                        00401b1f f   LIBC:crt0dat.obj
0001:00000b30   __exit                       00401b30 f   LIBC:crt0dat.obj
0001:00000bf4   __XcptFilter                 00401bf4 f   LIBC:winxfltr.obj
0001:00000d78   __setenvp                    00401d78 f   LIBC:stdenvp.obj
0001:00000e31   __setargv                    00401e31 f   LIBC:stdargv.obj
0001:0000107e   ___crtGetEnvironmentStringsA 0040207e f   LIBC:a_env.obj
0001:000011b0   __ioinit                     004021b0 f   LIBC:ioinit.obj
0001:0000135b   __heap_init                  0040235b f   LIBC:heapinit.obj
0001:00001398   __global_unwind2             00402398 f   LIBC:exsup.obj
0001:000013da   __local_unwind2              004023da f   LIBC:exsup.obj
0001:00001432   __NLG_Return2                00402432 f   LIBC:exsup.obj
0001:00001442   __abnormal_termination       00402442 f   LIBC:exsup.obj
0001:00001465   __NLG_Notify1                00402465 f   LIBC:exsup.obj
0001:0000146e   __NLG_Notify                 0040246e f   LIBC:exsup.obj
0001:00001481   __NLG_Dispatch               00402481 f   LIBC:exsup.obj
0001:00001490   __except_handler3            00402490 f   LIBC:exsup3.obj
0001:0000154d   __seh_longjmp_unwind@4       0040254d f   LIBC:exsup3.obj
0001:00001568   __FF_MSGBANNER               00402568 f   LIBC:crt0msg.obj
0001:000015a1   __NMSG_WRITE                 004025a1 f   LIBC:crt0msg.obj
0001:000016f4   _malloc                      004026f4 f   LIBC:malloc.obj
0001:00001706   __nh_malloc                  00402706 f   LIBC:malloc.obj
0001:00001732   __heap_alloc                 00402732 f   LIBC:malloc.obj
0001:00001768   __isatty                     00402768 f   LIBC:isatty.obj
0001:0000178e   _fflush                      0040278e f   LIBC:fflush.obj
0001:000017c9   __flush                      004027c9 f   LIBC:fflush.obj
0001:00001825   __flushall                   00402825 f   LIBC:fflush.obj
0001:000018a0   _strlen                      004028a0 f   LIBC:strlen.obj
0001:0000191b   _wctomb                      0040291b f   LIBC:wctomb.obj
0001:00001990   __aulldiv                    00402990 f   LIBC:ulldiv.obj
0001:00001a00   __aullrem                    00402a00 f   LIBC:ullrem.obj
0001:00001a75   __flsbuf                     00402a75 f   LIBC:_flsbuf.obj
0001:00001b8a   _calloc                      00402b8a f   LIBC:calloc.obj
0001:00001c07   __fcloseall                  00402c07 f   LIBC:closeall.obj
0001:00001c5f   _free                        00402c5f f   LIBC:free.obj
0001:00001c90   _strcpy                      00402c90 f   LIBC:strcat.obj
0001:00001ca0   _strcat                      00402ca0 f   LIBC:strcat.obj
0001:00001d80   __setmbcp                    00402d80 f   LIBC:mbctype.obj
0001:00002144   ___initmbctable              00403144 f   LIBC:mbctype.obj
0001:00002160   _memcpy                      00403160 f   LIBC:memcpy.obj
0001:00002495   ___sbh_heap_init             00403495 f   LIBC:sbheap.obj
0001:000024d3   ___sbh_find_block            004034d3 f   LIBC:sbheap.obj
0001:000024fe   ___sbh_free_block            004034fe f   LIBC:sbheap.obj
0001:00002829   ___sbh_alloc_block           00403829 f   LIBC:sbheap.obj
0001:00002b32   ___sbh_alloc_new_region      00403b32 f   LIBC:sbheap.obj
0001:00002be3   ___sbh_alloc_new_group       00403be3 f   LIBC:sbheap.obj
0001:00002cde   ___crtMessageBoxA            00403cde f   LIBC:crtmbox.obj
0001:00002d70   _strncpy                     00403d70 f   LIBC:strncpy.obj
0001:00002e6e   __callnewh                   00403e6e f   LIBC:handler.obj
0001:00002e89   __commit                     00403e89 f   LIBC:commit.obj
0001:00002ee0   __write                      00403ee0 f   LIBC:write.obj
0001:0000308d   __fptrap                     0040408d f   LIBC:crt0fp.obj
0001:00003096   __lseek                      00404096 f   LIBC:lseek.obj
0001:00003130   __getbuf                     00404130 f   LIBC:_getbuf.obj
0001:00003180   _memset                      00404180 f   LIBC:memset.obj
0001:000031d8   _fclose                      004041d8 f   LIBC:fclose.obj
0001:0000322e   ___crtLCMapStringA           0040422e f   LIBC:a_map.obj
0001:0000347d   ___crtGetStringTypeA         0040447d f   LIBC:a_str.obj
0001:000035d0   _memmove                     004045d0 f   LIBC:memmove.obj
0001:00003905   __free_osfhnd                00404905 f   LIBC:osfinfo.obj
0001:0000397f   __get_osfhandle              0040497f f   LIBC:osfinfo.obj
0001:000039bc   __dosmaperr                  004049bc f   LIBC:dosmap.obj
0001:00003a23   __close                      00404a23 f   LIBC:close.obj
0001:00003ad6   __freebuf                    00404ad6 f   LIBC:_freebuf.obj
0001:00003b10   __alloca_probe               00404b10 f   LIBC:chkstk.obj
0001:00003b10   __chkstk                     00404b10 f   LIBC:chkstk.obj
</pre>

<hr color="#000080">
<a name="fig2">Figure 2</a> PRINTF.CPP<br>
<pre class=code>
//==========================================
// LIBCTINY - Matt Pietrek 2001
// MSDN Magazine, January 2001
//==========================================
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdarg.h&gt;

// Force the linker to include USER32.LIB
#pragma comment(linker, &quot;/defaultlib:user32.lib&quot;)

extern &quot;C&quot; int __cdecl printf(const char * format, ...)
{
  char szBuff[1024];
  int retValue;
  DWORD cbWritten;
  va_list argptr;

  va_start( argptr, format );
  retValue = wvsprintf( szBuff, format, argptr );
  va_end( argptr );

  WriteFile(  GetStdHandle(STD_OUTPUT_HANDLE), szBuff, retValue,
              &amp;cbWritten, 0 );

  return retValue;
}
</pre>

<hr color="#000080">
<a name="fig3">Figure 3</a> INITTERM<br>
<pre class=code>
//==========================================
// LIBCTINY - Matt Pietrek 2001
// MSDN Magazine, January 2001
//==========================================
#include &lt;windows.h&gt;
#include &lt;malloc.h&gt;
#include &quot;initterm.h&quot;

#pragma data_seg(&quot;.CRT$XCA&quot;)
_PVFV __xc_a[] = { NULL };


#pragma data_seg(&quot;.CRT$XCZ&quot;)
_PVFV __xc_z[] = { NULL };

#pragma data_seg()  /* reset */

#pragma comment(linker, &quot;/merge:.CRT=.data&quot;)

typedef void (__cdecl *_PVFV)(void);

void __cdecl _initterm (
        _PVFV * pfbegin,
        _PVFV * pfend
        )
{
  /*
   * walk the table of function pointers from the bottom up, until
   * the end is encountered.  Do not skip the first entry.  The initial
   * value of pfbegin points to the first valid entry.  Do not try to
   * execute what pfend points to.  Only entries before pfend are
   * valid.
   */
  while ( pfbegin &lt; pfend )
  {
    // if current table entry is non-NULL, call thru it.
    if ( *pfbegin != NULL )
      (**pfbegin)();
    ++pfbegin;
  }
}

static _PVFV * pf_atexitlist = 0;
static unsigned max_atexitlist_entries = 0;
static unsigned cur_atexitlist_entries = 0;

void __cdecl _atexit_init(void)
{
  max_atexitlist_entries = 32;
  pf_atexitlist = (_PVFV *)calloc( max_atexitlist_entries,
                                   sizeof(_PVFV*) );
}

int __cdecl atexit (_PVFV func )
{
  if ( cur_atexitlist_entries &lt; max_atexitlist_entries )
  {
    pf_atexitlist[cur_atexitlist_entries++] = func;
    return 0;
  }

  return -1;
}

void __cdecl _DoExit( void )
{
  if ( cur_atexitlist_entries )
  {
    _initterm( pf_atexitlist,
               // Use ptr math to find the end of the array
               pf_atexitlist + cur_atexitlist_entries );
  }
}
</pre>
<hr color="#000080">
<span class="clsFigure"><a name="fig4">Figure 4</a></span> <span class="clsCap">DLLCRTO.CPP</span><br>
<pre class=code>
//==========================================
// LIBCTINY - Matt Pietrek 2001
// MSDN Magazine, January 2001
// FILE: DLLCRT0.CPP
//==========================================
#include &lt;windows.h&gt;
#include &quot;initterm.h&quot;

// Force the linker to include KERNEL32.LIB
#pragma comment(linker, &quot;/defaultlib:kernel32.lib&quot;)

// Force 512 byte section alignment in the PE file
#pragma comment(linker, &quot;/OPT:NOWIN98&quot;)

// #pragma comment(linker, &quot;/nodefaultlib:libc.lib&quot;)
// #pragma comment(linker, &quot;/nodefaultlib:libcmt.lib&quot;)

// User routine DllMain is called on all notifications

extern BOOL WINAPI DllMain(
                           HANDLE  hDllHandle,
                           DWORD   dwReason,
                           LPVOID  lpreserved
                           ) ;

//
// Modified version of the Visual C++ startup code.  Simplified to
// make it easier to read.  Only supports ANSI programs.
//
extern &quot;C&quot;
BOOL WINAPI _DllMainCRTStartup(
                               HANDLE  hDllHandle,
                               DWORD   dwReason,
                               LPVOID  lpreserved
                               )
{
  if ( dwReason == DLL_PROCESS_ATTACH )
  {
    // set up our minimal cheezy atexit table
    _atexit_init();

    // Call C++ constructors
    _initterm( __xc_a, __xc_z );
  }

  BOOL retcode = DllMain(hDllHandle, dwReason, lpreserved);

  if ( dwReason == DLL_PROCESS_DETACH )
  {
    _DoExit();
  }

  return retcode ;
}
</pre>

<hr color="#000080">
<a name="fig5">Figure 5</a> TEST.CPP<br>
<pre class=code>
// Small test program to exercise TINYCRT.  Does nothing useful
//
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int main( int argc, char *argv[] )
{
  int i;

  for ( i = 0; i &lt; argc; i++ )
  {
    printf( &quot;argc: %u \'%s\'\n&quot;, i, argv[i] );
  }

  char * p = new char[10];
  lstrcpy( p, &quot;Hello&quot; );
  delete p;

  printf( &quot;%s\n&quot;, strlwr( &quot;MyLowerCaseString&quot; ) );
  printf ( &quot;strcmpi: %u\n&quot;, strcmpi( &quot;Abc&quot;, &quot;abc&quot; ) );
  strrchr( &quot;foo&quot;, 'o' );

  return 0;
}

// Declare a simple C++ class with a constructor
class TestClass
{
public:
  TestClass(void)
  {
    printf( &quot;In TestClass constructor\n&quot; );
  }
  ~TestClass(void)
  {
    printf( &quot;In TestClass destructor\n&quot; );
  }
};

// Create a global instance of the class
TestClass g_TestClassInstance;
</pre>

</body>

</html>
